﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.ApplicationModel.Resources.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using System.Collections.Specialized;

//New using
using System.Data.Services.Client;
using havivi.sharepoint.lists.SharePointService;
using System.Net;
using System.Text.RegularExpressions;

// The data model defined by this file serves as a representative example of a strongly-typed
// model that supports notification when members are added, removed, or modified.  The property
// names chosen coincide with data bindings in the standard item templates.
//
// Applications may use this model as a starting point and build on it, or discard it entirely and
// replace it with something appropriate to their needs.

namespace havivi.sharepoint.lists.Data
{
    /// <summary>
    /// Base class for <see cref="SharePointDataItem"/> and <see cref="SharePointDataGroup"/> that
    /// defines properties common to both.
    /// </summary>
    [Windows.Foundation.Metadata.WebHostHidden]
    public abstract class SharePointDataCommon : havivi.sharepoint.lists.Common.BindableBase
    {
        private static Uri _baseUri = new Uri("ms-appx:///");

        public SharePointDataCommon(String uniqueId, String title, String subtitle, String imagePath, String description)
        {
            this._uniqueId = uniqueId;
            this._title = title;
            this._subtitle = subtitle;
            this._description = description;
            this._imagePath = imagePath;
        }

        private string _uniqueId = string.Empty;
        public string UniqueId
        {
            get { return this._uniqueId; }
            set { this.SetProperty(ref this._uniqueId, value); }
        }

        private string _title = string.Empty;
        public string Title
        {
            get { return this._title; }
            set { this.SetProperty(ref this._title, value); }
        }

        private string _subtitle = string.Empty;
        public string Subtitle
        {
            get { return this._subtitle; }
            set { this.SetProperty(ref this._subtitle, value); }
        }

        private string _description = string.Empty;
        public string Description
        {
            get { return this._description; }
            set { this.SetProperty(ref this._description, value); }
        }

        private ImageSource _image = null;
        private String _imagePath = null;
        public ImageSource Image
        {
            get
            {
                if (this._image == null && this._imagePath != null)
                {
                    this._image = new BitmapImage(new Uri(SharePointDataCommon._baseUri, this._imagePath));
                }
                return this._image;
            }

            set
            {
                this._imagePath = null;
                this.SetProperty(ref this._image, value);
            }
        }

        public void SetImage(String path)
        {
            this._image = null;
            this._imagePath = path;
            this.OnPropertyChanged("Image");
        }

        public override string ToString()
        {
            return this.Title;
        }
    }

    /// <summary>
    /// Generic item data model.
    /// </summary>
    public class SharePointDataItem : SharePointDataCommon
    {
        public SharePointDataItem(String uniqueId, String title, String subtitle, String imagePath, String description, String content, SharePointDataGroup group)
            : base(uniqueId, title, subtitle, imagePath, description)
        {
            this._content = content;
            this._group = group;
        }

        private string _content = string.Empty;
        public string Content
        {
            get { return this._content; }
            set { this.SetProperty(ref this._content, value); }
        }

        private SharePointDataGroup _group;
        public SharePointDataGroup Group
        {
            get { return this._group; }
            set { this.SetProperty(ref this._group, value); }
        }
    }

    /// <summary>
    /// Generic group data model.
    /// </summary>
    public class SharePointDataGroup : SharePointDataCommon
    {
        public SharePointDataGroup(String uniqueId, String title, String subtitle, String imagePath, String description)
            : base(uniqueId, title, subtitle, imagePath, description)
        {
            Items.CollectionChanged += ItemsCollectionChanged;
        }

        private void ItemsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            // Provides a subset of the full items collection to bind to from a GroupedItemsPage
            // for two reasons: GridView will not virtualize large items collections, and it
            // improves the user experience when browsing through groups with large numbers of
            // items.
            //
            // A maximum of 12 items are displayed because it results in filled grid columns
            // whether there are 1, 2, 3, 4, or 6 rows displayed

            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    if (e.NewStartingIndex < 12)
                    {
                        TopItems.Insert(e.NewStartingIndex, Items[e.NewStartingIndex]);
                        if (TopItems.Count > 12)
                        {
                            TopItems.RemoveAt(12);
                        }
                    }
                    break;
                case NotifyCollectionChangedAction.Move:
                    if (e.OldStartingIndex < 12 && e.NewStartingIndex < 12)
                    {
                        TopItems.Move(e.OldStartingIndex, e.NewStartingIndex);
                    }
                    else if (e.OldStartingIndex < 12)
                    {
                        TopItems.RemoveAt(e.OldStartingIndex);
                        TopItems.Add(Items[11]);
                    }
                    else if (e.NewStartingIndex < 12)
                    {
                        TopItems.Insert(e.NewStartingIndex, Items[e.NewStartingIndex]);
                        TopItems.RemoveAt(12);
                    }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    if (e.OldStartingIndex < 12)
                    {
                        TopItems.RemoveAt(e.OldStartingIndex);
                        if (Items.Count >= 12)
                        {
                            TopItems.Add(Items[11]);
                        }
                    }
                    break;
                case NotifyCollectionChangedAction.Replace:
                    if (e.OldStartingIndex < 12)
                    {
                        TopItems[e.OldStartingIndex] = Items[e.OldStartingIndex];
                    }
                    break;
                case NotifyCollectionChangedAction.Reset:
                    TopItems.Clear();
                    while (TopItems.Count < Items.Count && TopItems.Count < 12)
                    {
                        TopItems.Add(Items[TopItems.Count]);
                    }
                    break;
            }
        }

        private ObservableCollection<SharePointDataItem> _items = new ObservableCollection<SharePointDataItem>();
        public ObservableCollection<SharePointDataItem> Items
        {
            get { return this._items; }
        }

        private ObservableCollection<SharePointDataItem> _topItem = new ObservableCollection<SharePointDataItem>();
        public ObservableCollection<SharePointDataItem> TopItems
        {
            get { return this._topItem; }
        }
    }

    /// <summary>
    /// Creates a collection of groups and items with hard-coded content.
    /// 
    /// SharePointDataSource initializes with placeholder data rather than live production
    /// data so that sample data is provided at both design-time and run-time.
    /// </summary>
    public sealed class SharePointDataSource
    {

        private static SharePointDataSource _SharePointDataSource = new SharePointDataSource();
        //New 
        private DataServiceCollection<AnnouncementsItem> announcements = new DataServiceCollection<AnnouncementsItem>();
        private DataServiceCollection<SharedDocumentsItem> sharedDocuments = new DataServiceCollection<SharedDocumentsItem>();
        private DataServiceCollection<CalendarItem> calendar = new DataServiceCollection<CalendarItem>();
        private DataServiceCollection<TasksItem> tasks = new DataServiceCollection<TasksItem>();
        private TeamSiteDataContext context;

        private ObservableCollection<SharePointDataGroup> _allGroups = new ObservableCollection<SharePointDataGroup>();
        public ObservableCollection<SharePointDataGroup> AllGroups
        {
            get { return this._allGroups; }
        }

        public static IEnumerable<SharePointDataGroup> GetGroups(string uniqueId)
        {
            if (!uniqueId.Equals("AllGroups")) throw new ArgumentException("Only 'AllGroups' is supported as a collection of groups");

            return _SharePointDataSource.AllGroups;
        }

        public static SharePointDataGroup GetGroup(string uniqueId)
        {
            // Simple linear search is acceptable for small data sets
            var matches = _SharePointDataSource.AllGroups.Where((group) => group.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        public static SharePointDataItem GetItem(string uniqueId)
        {
            // Simple linear search is acceptable for small data sets
            var matches = _SharePointDataSource.AllGroups.SelectMany(group => group.Items).Where((item) => item.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        public SharePointDataSource()
        {
            context = new TeamSiteDataContext(new Uri("http://spfoundation/sites/TeamSite/_vti_bin/ListData.svc"));
            NetworkCredential credentials = new NetworkCredential();
            context.UseDefaultCredentials = false;
            context.Credentials = new NetworkCredential("emily", "welkom1234#", "spfoundation");

            announcements = new DataServiceCollection<AnnouncementsItem>();
            announcements.LoadAsync(context.Announcements);
            announcements.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(announcements_LoadCompleted);

            tasks = new DataServiceCollection<TasksItem>();
            tasks.LoadAsync(context.Tasks);
            tasks.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(tasks_LoadCompleted);

            calendar = new DataServiceCollection<CalendarItem>();
            calendar.LoadAsync(context.Calendar);
            calendar.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(calendar_LoadCompleted);

            sharedDocuments = new DataServiceCollection<SharedDocumentsItem>();
            sharedDocuments.LoadAsync(context.SharedDocuments);
            sharedDocuments.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(sharedDocuments_LoadCompleted);
        }

        void announcements_LoadCompleted(object sender, LoadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                var group = new SharePointDataGroup("Announcements",
                                                       "Announcements",
                                                       "Team Announcement",
                                                       "Assets/ANNOUNCE.png",
                                                       "Use this list to track upcoming events, status updates or other team news.");

                int index = 0;
                foreach (var item in announcements)
                {
                    group.Items.Add(new SharePointDataItem("Announcements-Item-" + index,
                           item.Title,
                           item.Modified.ToString(),
                           "Assets/ANNOUNCE.png",
                           item.Version,
                           RemoveHtml(item.Body),
                           group));

                    index++;
                }
                this.AllGroups.Add(group);
            }
            else
            {
                //   Error
            }
        }

        void sharedDocuments_LoadCompleted(object sender, LoadCompletedEventArgs e)
        {

            if (e.Error == null)
            {
                var group = new SharePointDataGroup("Shared Documents",
                       "Shared Documents",
                       "Teamsite",
                       "Assets/document.png",
                        "Share a document with the team by adding it to this document library.");

                int index = 0;
                foreach (var item in sharedDocuments)
                {
                    group.Items.Add(new SharePointDataItem("Document-Item-" + index,
                            item.Name,
                           item.Modified.ToString(),
                            "Assets/document.png",
                            item.Version,
                            "",
                            group));

                    index++;
                }
                this.AllGroups.Add(group);
            }
            else
            {
                //   Error
            }
        }

        void calendar_LoadCompleted(object sender, LoadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                var group = new SharePointDataGroup("Calendar",
                       "Calendar",
                       "Teamsite Calendar",
                       "Assets/calander.png",
                       "Use the Calendar list to keep informed of upcoming meetings, deadlines, and other important events.");

                int index = 0;
                foreach (var item in calendar)
                {
                    group.Items.Add(new SharePointDataItem("Calendar-Item-" + index,
                            item.Title,
                            item.Modified.ToString(),
                            "Assets/calander.png",
                            item.Version,
                            item.Description,
                            group));

                    index++;
                }
                this.AllGroups.Add(group);
            }
            else
            {
                //   Error
            }
        }

        void tasks_LoadCompleted(object sender, LoadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                var group = new SharePointDataGroup("Tasks",
                       "Tasks",
                       "Teamsite tasks",
                       "Assets/tasks.png",
                        "Use the Tasks list to keep track of work that you or your team needs to complete.");

                int index = 0;
                foreach (var item in tasks)
                {

                    group.Items.Add(new SharePointDataItem("Task-Item-" + index,
                            item.Title,
                            item.Modified.ToString(),
                            "Assets/tasks.png",
                            item.Version,
                            RemoveHtml(item.Description),
                            group));

                    index++;
                }
                this.AllGroups.Add(group);
            }
            else
            {
                //   Error
            }
        }

        private string RemoveHtml(string text)
        {
            return Regex.Replace(text, @"<(.|\n)*?>", string.Empty);
        }
    }
}
